 package com.gmrz.uaf.protocol.v1.json;
 
 import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import com.gmrz.uaf.protocol.v1.schema.Base64URLEncoded;
import com.gmrz.util.Convert;
 
 public class Base64URLEncodedAdapter<T>
   implements JsonSerializer<Base64URLEncoded<T>>, JsonDeserializer<Base64URLEncoded<T>>
 {
   TypeToken<T> dataType = null;
 
   public Base64URLEncodedAdapter(TypeToken<T> dataType) {
     this.dataType = dataType;
   }
 
   public JsonElement serialize(Base64URLEncoded<T> src, Type typeofSrc, JsonSerializationContext context)
   {
     if ((src == null) || (src.getData() == null)) {
       return JsonNull.INSTANCE;
     }
 
     if (this.dataType.getRawType().isAssignableFrom(Base64URLEncoded.class))
       return context.serialize(Convert.toBase64((byte[])src.getData()));
     if (this.dataType.getRawType().isAssignableFrom(String.class))
       try {
         byte[] data = Convert.toUtf8((String)src.getData());
         return context.serialize(Convert.toBase64(data));
       } catch (UnsupportedEncodingException e) {
         throw new RuntimeException("Error encoding data: " + e.getMessage(), e);
       }
     try
     {
       String json = UAFSchemaBuilder.getGson().toJson(src.getData());
       byte[] data = Convert.toUtf8(json);
       return context.serialize(Convert.toBase64(data));
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("Error encoding data: " + e.getMessage(), e);
     }
   }
 
   public Base64URLEncoded<T> deserialize(JsonElement json, Type typeofT, JsonDeserializationContext context)
     throws JsonParseException
   {
     String b64str = json.getAsString();
 
     if (this.dataType.getRawType().isAssignableFrom(Base64URLEncoded.class)) {
       return new Base64URLEncoded(Convert.fromBase64(b64str));
     }
     if (this.dataType.getRawType().isAssignableFrom(String.class)) {
       try {
         byte[] data = Convert.fromBase64(b64str);
         String str = Convert.fromUtf8(data);
         return new Base64URLEncoded(str);
       } catch (UnsupportedEncodingException e) {
         throw new RuntimeException("Error encoding data: " + e.getMessage(), e);
       }
     }
     try
     {
       byte[] data = Convert.fromBase64(b64str);
       String str = Convert.fromUtf8(data);
       Object obj = UAFSchemaBuilder.getGson().fromJson(str, this.dataType.getType());
       return new Base64URLEncoded(obj);
     } catch (UnsupportedEncodingException e) {
       throw new RuntimeException("Error encoding data: " + e.getMessage(), e);
     }
   }
 }
